// VTKCompassStudio.cpp
#include "VTKCompassStudio.h"

#include <vtkProperty.h>
#include <vtkPolyDataMapper.h>
#include <vtkLineSource.h>
#include <vtkVectorText.h>

VTKCompassStudio::VTKCompassStudio(QObject* parent)
    : QObject(parent),
      m_renderer(nullptr),
      m_visible(false),
      m_directionLabelsVisible(true),
      m_diagonalLinesVisible(true),
      m_scale(1.0),
      m_diskOpacity(0.3),
      m_textAndLineOpacity(1.0),
      m_innerRadius(4.0),
      m_outerRadius(5.0),
      m_radialResolution(1),
      m_circumferentialResolution(50),
      m_lineWidth(2.0)
{
    // 初始化位置
    m_position[0] = 0.0;
    m_position[1] = 0.0;
    m_position[2] = 0.0;

    // 初始化颜色 (浅灰色圆盘，红色文字和线条)
    m_diskColor[0] = 0.8;
    m_diskColor[1] = 0.8;
    m_diskColor[2] = 0.8;
    m_textAndLineColor[0] = 1.0;
    m_textAndLineColor[1] = 0.0;
    m_textAndLineColor[2] = 0.0;

    createCompass();
}

VTKCompassStudio::~VTKCompassStudio()
{
    setVisible(false);
}

void VTKCompassStudio::createCompass()
{
    // 创建罗盘圆盘
    m_diskSource = vtkSmartPointer<vtkDiskSource>::New();
    m_diskSource->SetInnerRadius(m_innerRadius);
    m_diskSource->SetOuterRadius(m_outerRadius);
    m_diskSource->SetRadialResolution(m_radialResolution);
    m_diskSource->SetCircumferentialResolution(m_circumferentialResolution);

    vtkSmartPointer<vtkPolyDataMapper> diskMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    diskMapper->SetInputConnection(m_diskSource->GetOutputPort());

    m_diskActor = vtkSmartPointer<vtkActor>::New();
    m_diskActor->SetMapper(diskMapper);
    m_diskActor->SetPosition(m_position[0], m_position[1], m_position[2]);
    m_diskActor->SetScale(m_scale);

    // 创建方向文字 - 文字位置在圆环上
    double textRadius = (m_innerRadius + m_outerRadius) / 2.0;  // 文字放在圆环中间位置
    createDirectionText("N", m_northText, textRadius, 0.0, 0.001);
    createDirectionText("S", m_southText, -textRadius, 0.0, 0.001);
    createDirectionText("E", m_eastText, 0.0, -textRadius, 0.001);
    createDirectionText("W", m_westText, 0.0, textRadius, 0.001);

    // 创建刻度线
    createDiagonalLine(m_neLine, 45.0);
    createDiagonalLine(m_seLine, 135.0);
    createDiagonalLine(m_swLine, 225.0);
    createDiagonalLine(m_nwLine, 315.0);

    // 应用初始属性
    updateAllProperties();
}

void VTKCompassStudio::createDirectionText(const char* text, vtkSmartPointer<vtkActor>& textActor, double x, double y, double z)
{
    vtkSmartPointer<vtkVectorText> textSource = vtkSmartPointer<vtkVectorText>::New();
    textSource->SetText(text);

    vtkSmartPointer<vtkPolyDataMapper> textMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    textMapper->SetInputConnection(textSource->GetOutputPort());

    textActor = vtkSmartPointer<vtkActor>::New();
    textActor->SetMapper(textMapper);

    // 更精确的位置计算
    double textRadius = (m_outerRadius - m_innerRadius);

    if (strcmp(text, "N") == 0)
    {
        textActor->SetPosition(x - textRadius, y, z);
        textActor->SetOrientation(0, 0, -90);
    }
    else if (strcmp(text, "S") == 0)
    {
        textActor->SetPosition(x, y, z);
        textActor->SetOrientation(0, 0, -90);
    }
    else if (strcmp(text, "E") == 0)
    {
        textActor->SetPosition(x, y, z);
        textActor->SetOrientation(0, 0, 0);
    }
    else if (strcmp(text, "W") == 0)
    {
        textActor->SetPosition(x, y + textRadius, z);
        textActor->SetOrientation(0, 0, 0);
    }

    // 自动计算文字大小
    updateTextSize();
}

void VTKCompassStudio::createDiagonalLine(vtkSmartPointer<vtkActor>& lineActor, double angleDegrees)
{
    double angle = angleDegrees * 3.141592653589793 / 180.0;
    double cosAngle = cos(angle);
    double sinAngle = sin(angle);

    double startPoint[3] = {m_innerRadius * cosAngle, m_innerRadius * sinAngle, 0.002};
    double endPoint[3] = {m_outerRadius * cosAngle, m_outerRadius * sinAngle, 0.002};

    vtkSmartPointer<vtkLineSource> lineSource = vtkSmartPointer<vtkLineSource>::New();
    lineSource->SetPoint1(startPoint);
    lineSource->SetPoint2(endPoint);

    vtkSmartPointer<vtkPolyDataMapper> lineMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    lineMapper->SetInputConnection(lineSource->GetOutputPort());

    lineActor = vtkSmartPointer<vtkActor>::New();
    lineActor->SetMapper(lineMapper);
}

void VTKCompassStudio::updateTextSize()
{
    // 文字大小 = 圆环宽度 * 80%
    double ringWidth = m_outerRadius - m_innerRadius;
    double textSize = ringWidth * 0.5;
    double textScale = textSize * m_scale;

    if (m_northText)
        m_northText->SetScale(textScale);
    if (m_southText)
        m_southText->SetScale(textScale);
    if (m_eastText)
        m_eastText->SetScale(textScale);
    if (m_westText)
        m_westText->SetScale(textScale);
}

void VTKCompassStudio::setVisible(bool visible)
{
    if (m_visible == visible || !m_renderer)
        return;

    m_visible = visible;

    if (visible)
    {
        m_renderer->AddActor(m_diskActor);

        if (m_directionLabelsVisible)
        {
            m_renderer->AddActor(m_northText);
            m_renderer->AddActor(m_southText);
            m_renderer->AddActor(m_eastText);
            m_renderer->AddActor(m_westText);
        }

        if (m_diagonalLinesVisible)
        {
            m_renderer->AddActor(m_neLine);
            m_renderer->AddActor(m_seLine);
            m_renderer->AddActor(m_swLine);
            m_renderer->AddActor(m_nwLine);
        }
    }
    else
    {
        m_renderer->RemoveActor(m_diskActor);
        m_renderer->RemoveActor(m_northText);
        m_renderer->RemoveActor(m_southText);
        m_renderer->RemoveActor(m_eastText);
        m_renderer->RemoveActor(m_westText);
        m_renderer->RemoveActor(m_neLine);
        m_renderer->RemoveActor(m_seLine);
        m_renderer->RemoveActor(m_swLine);
        m_renderer->RemoveActor(m_nwLine);
    }
}

void VTKCompassStudio::setRenderer(vtkRenderer* renderer)
{
    if (m_renderer == renderer)
        return;

    // 从旧渲染器移除
    if (m_renderer && m_visible)
    {
        setVisible(false);
    }

    m_renderer = renderer;

    // 添加到新渲染器
    if (m_renderer && m_visible)
    {
        setVisible(true);
    }
}

void VTKCompassStudio::setPosition(double x, double y, double z)
{
    m_position[0] = x;
    m_position[1] = y;
    m_position[2] = z;

    m_diskActor->SetPosition(x, y, z);
    updateTextPositions();
    updateLinePositions();
}

void VTKCompassStudio::getPosition(double& x, double& y, double& z) const
{
    x = m_position[0];
    y = m_position[1];
    z = m_position[2];
}

void VTKCompassStudio::setScale(double scale)
{
    if (m_scale == scale)
        return;

    m_scale = scale;
    m_diskActor->SetScale(scale);

    // 更新文字大小
    updateTextSize();
    updateTextPositions();
    updateLinePositions();
}

void VTKCompassStudio::updateTextPositions()
{
    double textRadius = (m_innerRadius + m_outerRadius) / 2.0 * m_scale;
    double offset = (m_outerRadius - m_innerRadius) * m_scale;

    // 更精确的位置计算，考虑缩放
    m_northText->SetPosition(m_position[0] + textRadius - (offset * 0.2), m_position[1] + (offset * 0.3), m_position[2] + 0.001);
    m_southText->SetPosition(m_position[0] - textRadius - (offset * 0.2), m_position[1] + (offset * 0.3), m_position[2] + 0.001);
    m_eastText->SetPosition(m_position[0], m_position[1] - textRadius - (offset * 0.2), m_position[2] + 0.001);
    m_westText->SetPosition(m_position[0], m_position[1] + textRadius - (offset * 0.2), m_position[2] + 0.001);
}

void VTKCompassStudio::updateLinePositions()
{
    const double angles[4] = {45.0, 135.0, 225.0, 315.0};
    vtkActor* lines[4] = {m_neLine.Get(), m_seLine.Get(), m_swLine.Get(), m_nwLine.Get()};

    for (int i = 0; i < 4; ++i)
    {
        if (lines[i])
        {
            double angle = angles[i] * 3.141592653589793 / 180.0;
            double cosAngle = cos(angle);
            double sinAngle = sin(angle);

            double innerRadius = m_innerRadius * m_scale;
            double outerRadius = m_outerRadius * m_scale;

            double startPoint[3] = {m_position[0] + innerRadius * cosAngle, m_position[1] + innerRadius * sinAngle, m_position[2] + 0.002};
            double endPoint[3] = {m_position[0] + outerRadius * cosAngle, m_position[1] + outerRadius * sinAngle, m_position[2] + 0.002};

            vtkSmartPointer<vtkLineSource> lineSource = vtkSmartPointer<vtkLineSource>::New();
            lineSource->SetPoint1(startPoint);
            lineSource->SetPoint2(endPoint);

            vtkSmartPointer<vtkPolyDataMapper> lineMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
            lineMapper->SetInputConnection(lineSource->GetOutputPort());
            lines[i]->SetMapper(lineMapper);
        }
    }
}

// 颜色设置方法
void VTKCompassStudio::setDiskColor(double r, double g, double b)
{
    m_diskColor[0] = r;
    m_diskColor[1] = g;
    m_diskColor[2] = b;
    m_diskActor->GetProperty()->SetColor(r, g, b);
}

void VTKCompassStudio::setDiskColor(const QColor& color)
{
    setDiskColor(color.redF(), color.greenF(), color.blueF());
}

QColor VTKCompassStudio::getDiskColor() const
{
    return QColor::fromRgbF(m_diskColor[0], m_diskColor[1], m_diskColor[2]);
}

void VTKCompassStudio::setTextAndLineColor(double r, double g, double b)
{
    m_textAndLineColor[0] = r;
    m_textAndLineColor[1] = g;
    m_textAndLineColor[2] = b;

    // 设置文字颜色
    m_northText->GetProperty()->SetColor(r, g, b);
    m_southText->GetProperty()->SetColor(r, g, b);
    m_eastText->GetProperty()->SetColor(r, g, b);
    m_westText->GetProperty()->SetColor(r, g, b);

    // 设置线条颜色
    m_neLine->GetProperty()->SetColor(r, g, b);
    m_seLine->GetProperty()->SetColor(r, g, b);
    m_swLine->GetProperty()->SetColor(r, g, b);
    m_nwLine->GetProperty()->SetColor(r, g, b);
}

void VTKCompassStudio::setTextAndLineColor(const QColor& color)
{
    setTextAndLineColor(color.redF(), color.greenF(), color.blueF());
}

QColor VTKCompassStudio::getTextAndLineColor() const
{
    return QColor::fromRgbF(m_textAndLineColor[0], m_textAndLineColor[1], m_textAndLineColor[2]);
}

// 透明度设置方法
void VTKCompassStudio::setDiskOpacity(double opacity)
{
    m_diskOpacity = opacity;
    m_diskActor->GetProperty()->SetOpacity(opacity);
}

double VTKCompassStudio::getDiskOpacity() const
{
    return m_diskOpacity;
}

void VTKCompassStudio::setTextAndLineOpacity(double opacity)
{
    m_textAndLineOpacity = opacity;

    // 设置文字透明度
    m_northText->GetProperty()->SetOpacity(opacity);
    m_southText->GetProperty()->SetOpacity(opacity);
    m_eastText->GetProperty()->SetOpacity(opacity);
    m_westText->GetProperty()->SetOpacity(opacity);

    // 设置线条透明度
    m_neLine->GetProperty()->SetOpacity(opacity);
    m_seLine->GetProperty()->SetOpacity(opacity);
    m_swLine->GetProperty()->SetOpacity(opacity);
    m_nwLine->GetProperty()->SetOpacity(opacity);
}

double VTKCompassStudio::getTextAndLineOpacity() const
{
    return m_textAndLineOpacity;
}

// 圆环参数控制
void VTKCompassStudio::setDiskRadius(double innerRadius, double outerRadius)
{
    m_innerRadius = innerRadius;
    m_outerRadius = outerRadius;
    m_diskSource->SetInnerRadius(innerRadius);
    m_diskSource->SetOuterRadius(outerRadius);
    m_diskSource->Modified();

    // 更新文字大小和位置
    updateTextSize();
    updateTextPositions();
    updateLinePositions();
}

void VTKCompassStudio::getDiskRadius(double& innerRadius, double& outerRadius) const
{
    innerRadius = m_innerRadius;
    outerRadius = m_outerRadius;
}

void VTKCompassStudio::setDiskResolution(int radialResolution, int circumferentialResolution)
{
    m_radialResolution = radialResolution;
    m_circumferentialResolution = circumferentialResolution;
    m_diskSource->SetRadialResolution(radialResolution);
    m_diskSource->SetCircumferentialResolution(circumferentialResolution);
    m_diskSource->Modified();
}

void VTKCompassStudio::getDiskResolution(int& radialResolution, int& circumferentialResolution) const
{
    radialResolution = m_radialResolution;
    circumferentialResolution = m_circumferentialResolution;
}

// 线宽控制
void VTKCompassStudio::setLineWidth(double width)
{
    m_lineWidth = width;
    m_neLine->GetProperty()->SetLineWidth(width);
    m_seLine->GetProperty()->SetLineWidth(width);
    m_swLine->GetProperty()->SetLineWidth(width);
    m_nwLine->GetProperty()->SetLineWidth(width);
}

double VTKCompassStudio::getLineWidth() const
{
    return m_lineWidth;
}

// 方向标签控制
void VTKCompassStudio::setDirectionLabelsVisible(bool visible)
{
    if (m_directionLabelsVisible == visible)
        return;

    m_directionLabelsVisible = visible;

    if (m_renderer && m_visible)
    {
        if (visible)
        {
            m_renderer->AddActor(m_northText);
            m_renderer->AddActor(m_southText);
            m_renderer->AddActor(m_eastText);
            m_renderer->AddActor(m_westText);
        }
        else
        {
            m_renderer->RemoveActor(m_northText);
            m_renderer->RemoveActor(m_southText);
            m_renderer->RemoveActor(m_eastText);
            m_renderer->RemoveActor(m_westText);
        }
    }
}

bool VTKCompassStudio::areDirectionLabelsVisible() const
{
    return m_directionLabelsVisible;
}

void VTKCompassStudio::setDiagonalLinesVisible(bool visible)
{
    if (m_diagonalLinesVisible == visible)
        return;

    m_diagonalLinesVisible = visible;

    if (m_renderer && m_visible)
    {
        if (visible)
        {
            m_renderer->AddActor(m_neLine);
            m_renderer->AddActor(m_seLine);
            m_renderer->AddActor(m_swLine);
            m_renderer->AddActor(m_nwLine);
        }
        else
        {
            m_renderer->RemoveActor(m_neLine);
            m_renderer->RemoveActor(m_seLine);
            m_renderer->RemoveActor(m_swLine);
            m_renderer->RemoveActor(m_nwLine);
        }
    }
}

bool VTKCompassStudio::areDiagonalLinesVisible() const
{
    return m_diagonalLinesVisible;
}

void VTKCompassStudio::updateAllProperties()
{
    updateColors();
    updateOpacities();
    updateTextPositions();
    updateLinePositions();

    // 设置线宽
    setLineWidth(m_lineWidth);

    // 更新文字大小
    updateTextSize();
}

void VTKCompassStudio::updateColors()
{
    setDiskColor(m_diskColor[0], m_diskColor[1], m_diskColor[2]);
    setTextAndLineColor(m_textAndLineColor[0], m_textAndLineColor[1], m_textAndLineColor[2]);
}

void VTKCompassStudio::updateOpacities()
{
    setDiskOpacity(m_diskOpacity);
    setTextAndLineOpacity(m_textAndLineOpacity);
}